// Win_viaC.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <Windows.h>
#include <WinBase.h>
#include <iostream>

#include <string.h>

using namespace std;

/*** 1. create files and watch handels added to proccess and then removed as files are closed ***/
void createFiles();
/*** 2. Object Handle inheritance - creates file and writes text to file,
creates child process which inherets the file handle and also writes to this file  ***/
void objectHandleInheritance();
/** 3. create named mutex to be opened in another process **/ 
void namedObject();
/*** 4. procedure to prevent opening more than 1 instance of this process ***/
void singleInstance();


/*** 5. function copied from book - prints the base address of this program ***/
extern "C" const IMAGE_DOS_HEADER __ImageBase;
void dumpModule();
/*** 6. get command-line variables from function that is not main 
(and convert to regular ansi string to print) ***/
void getCommandLine();

int _tmain(int argc, _TCHAR* argv[])
{

	getCommandLine();
	
	return 0;
}


/*** 1. create files and watch handels added to proccess and then removed as files are closed ***/
void createFiles(){
	HANDLE* hFiles = new HANDLE[10];

	for(int i = 0 ; i < 10; i++){
		wchar_t* name = new wchar_t[50];
		wchar_t* s = new wchar_t[4];
		_itow_s(i, s, 2, 10);
		
		wcscpy(name, L"C:\\Users\\shoshana\\Desktop\\tst ");
		wcscat(name, s);
		wcscat(name, L".txt");
		
		hFiles[i] = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
		if(hFiles[i] == INVALID_HANDLE_VALUE){
			cout << "error !! " << endl;
		}
		Sleep(1000);
	}

	for(int i = 0; i < 10; i++){
		CloseHandle(hFiles[i]);
			Sleep(1000);
	}
}

/*** 2. Object Handle inheritance - creates file and writes text to file, creates child process which inherets the file handle and also writes to this file  ***/
void objectHandleInheritance(){
	//open file and create  handle
	wchar_t* fName = L"myFile.txt";
	
	SECURITY_ATTRIBUTES sa;
	sa.nLength = sizeof(sa);
	sa.lpSecurityDescriptor = NULL;
	sa.bInheritHandle=TRUE; //Make the returned handle inheritable.

	HANDLE fileHandle =  CreateFile(fName,									//file name
									GENERIC_READ | GENERIC_WRITE,			//desired access 
									FILE_SHARE_READ | FILE_SHARE_WRITE,		//share mode
									&sa,									//a pointer to a security_attributes structure (important for inheritance)
									CREATE_ALWAYS,							//creation disposition
									0,										//flags and attributes
									0										//a handle to a template file
									); 
	cout << fileHandle << endl;

	char text[] = "Text from parent\r\n";
	DWORD dwBytesToWrite  = (DWORD)strlen(text);
	DWORD dwBytesWritten = 0;
	BOOL bErrorFlag = FALSE;

	bErrorFlag = WriteFile(fileHandle, text, dwBytesToWrite, &dwBytesWritten, NULL);

	// create new process 
	PCTSTR appName = L"C:\\Users\\Shoshana\\Documents\\Visual Studio 2010\\Projects\\win-viac_repository\\Child_process\\Debug\\Child_process.exe";
	PCTSTR cmdLineArg;
	LPSTARTUPINFOW si = new STARTUPINFO();
	LPPROCESS_INFORMATION pi = new PROCESS_INFORMATION();

	ZeroMemory( si, sizeof(*si) );
    si->cb = sizeof(*si);
    ZeroMemory( pi, sizeof(*pi) );


	//wchar_t s[200];
	wchar_t s[200];
	swprintf(s, 200, L"%s %x", appName, fileHandle);


	  // Start the child process. 
    if( !CreateProcess( NULL,   // module name (if NUll function uses first part of command line variables)
        s,				// Command line variables
        NULL,           // Process handle not inheritable
        NULL,           // Thread handle not inheritable
        TRUE,			// Set handle inheritance to TRUE
        0,              // No creation flags
        NULL,           // Use parent's environment block
        NULL,           // Use parent's starting directory 
        si,            // Pointer to STARTUPINFO structure
        pi )           // Pointer to PROCESS_INFORMATION structure
    ) 
    {
        printf( "CreateProcess failed (%d).\n", GetLastError() );
        return;
    }

	
	bErrorFlag = CloseHandle(fileHandle); //important to close only AFTER creating child so that handle is inherited

    // Wait until child process exits.
    WaitForSingleObject( pi->hProcess, INFINITE );

    // Close process and thread handles. 
    CloseHandle( pi->hProcess );
    CloseHandle( pi->hThread );
}

/** 3. create named mutex to be opened in another process **/ 
void namedObject(){
	HANDLE mutexHandle = CreateMutex(NULL,			//ptr to security attributes(if null, handle can't be inherited)
									 TRUE,			//initial owner
									 L"myMutex");
	CloseHandle(mutexHandle);
}

/*** 4. procedure to prevent opening more than 1 instance of this process ***/
void singleInstance(){
	//run the program - than u have 5 seconds to run it again and see what happens..
	HANDLE h = CreateMutex(NULL, FALSE, L"myMutex");
	if(GetLastError() == ERROR_ALREADY_EXISTS){
		//this isn't the first time this process has been started
		cout << "opening multiple instances of this process is forbidden !" << endl;
		CloseHandle(h);
		return;
	}else{
		cout << "first time running" << endl;
		//continue with all the stuff u wanna do (for this example it's just to wait for 5 seconds)
		Sleep(5000); 
		CloseHandle(h);
	}
}




/*** 5. function copied from book - prints the base address of this program ***/
void dumpModule(){

	// Get the base address of the running application.
	// Can be different from the running module if this code is in a DLL.
	HMODULE hModule = GetModuleHandle(NULL);
	_tprintf(TEXT("with GetModuleHandle(NULL) = 0x%x\r\n"), hModule);
	// Use the pseudo-variable __ImageBase to get
	// the address of the current module hModule/hInstance.
	_tprintf(TEXT("with __ImageBase = 0x%x\r\n"), (HINSTANCE)&__ImageBase);
	// Pass the address of the current method DumpModule
	// as parameter to GetModuleHandleEx to get the address
	// of the current module hModule/hInstance.
	hModule = NULL;
	GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
					  (PCTSTR)dumpModule,
					  &hModule);
	_tprintf(TEXT("with GetModuleHandleEx = 0x%x\r\n"), hModule);
}

/*** 6. get command-line variables from function that is not main 
(and convert to regular ansi string to print) ***/
void getCommandLine(){
	//cout << _tcslen(GetCommandLine()) << endl;
	char str[501];
	WideCharToMultiByte( CP_ACP,            //code page (in this case the default windows ANSI code page
						 0,					//flags
						 GetCommandLine(),	//ptr to unicode string
						 -1,				//size (in bytes) of unicode string (can be set to -1 if the string is null terminated)
						 str,				//ptr to buffer that receives converted string
						 500,				//buffer length
						 NULL,				//default character to use if can't convert unicode char
						 NULL);				//ptr to flag indicating if default char wa used
						 
	//cout << strlen(str) << endl;					 
	cout << str << endl << endl;

	//use CommandLineToArgvW to separate command line variables
	
}

